package graphic;

import java.awt.TexturePaint;
import java.io.File;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFunction;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;


public class CalculXY {

	public static String source;
	public static HashMap<String,Integer> xBoite;
	public static HashMap<String,Integer> yBoite;

	public CalculXY(String inPath) throws FileNotFoundException{
		CalculXY.source = inPath;
		CalculXY.xBoite=new HashMap<String,Integer>();
		CalculXY.yBoite =new HashMap<String,Integer>();
	}

	public static HashMap<String,Integer> CalculX() throws FileNotFoundException{


		//get all the nodes that are not links
		Vector<String> boxID=new Vector<String>();
		String e="//node()[@type!='MFHA_link'][@type!='MFHA_out_interface'][@type!='MFHA_in_interface']";
		NodeList n=(NodeList)TestXpath.evaluerSAX(CalculXY.source, e,XPathConstants.NODESET);

		if(n==null ||n.getLength()==0){
			System.out.println("here po de liste");
		}else{
			for (int i =0;i<n.getLength();i++){
				Element b=(Element)n.item(i);
				boxID.add(b.getAttribute("refID"));
			}
			System.out.println("tous les box : "+boxID.toString());
		}


		Boolean noOut=false;
		Vector<String> ids=new Vector<String>();
		int l=0;

		//list of boxs with in_interface
		String tt="//node()[@type!='MFHA_link'][@type!='MFHA_out_interface'][@type!='MFHA_in_interface']/node()[@type='MFHA_in_interface']";
		NodeList nIn=(NodeList) TestXpath.evaluerSAX(CalculXY.source, tt,XPathConstants.NODESET);
		Vector<String> refIn=new Vector<String>();
		for (int f=0;f<nIn.getLength();f++){
			Element ef=(Element)nIn.item(f);
			Element efRoot=(Element)ef.getParentNode();
			refIn.add(efRoot.getAttribute("refID"));
		}
		System.out.println ("liste des in : "+refIn.toString());

		//list of boxex without in
		Vector<String> boxWithoutIn=new Vector<String>();
		for (int y=0;y<boxID.size();y++){
			if(refIn.contains(boxID.get(y))==false){
				boxWithoutIn.add(boxID.get(y));
			}
		}

		System.out.println ("liste des with out in : "+boxWithoutIn.toString());



		//set up the box without in at first including the activator
		for (int y=0;y<boxWithoutIn.size();y++){
			CalculXY.xBoite.put(boxWithoutIn.get(y), l);
		}

		//add the activator to the Id vector, it will be the start of the treatement 
		String activId=(String)TestXpath.evaluerSAX(CalculXY.source,"/MFHA_graph/activator/@refID",XPathConstants.STRING);
		l+=20;
		ids.add(activId);
		//		System.out.println(activId);




		while (noOut==false){
			//the last placed box's id
			String lId = ids.lastElement();
			NodeList nOut=(NodeList)TestXpath.evaluerSAX(CalculXY.source, "//node()[@refID='"+lId+"']/node()[@type='MFHA_out_interface']",XPathConstants.NODESET);
			if(nOut.getLength()==1){
				Element et=(Element)nOut.item(0);
				String eID=et.getAttribute("refID");
				String exp="/MFHA_graph/link[init_interface[@refID='"+eID+"']]/finish_interface/@refID";
				String next=(String)TestXpath.evaluerSAX(CalculXY.source, exp,XPathConstants.STRING);
				String exp2="//node()[@type='MFHA_in_interface'][@refID='"+next+"']";
				Element nNext=(Element)TestXpath.evaluerSAX(CalculXY.source, exp2,XPathConstants.NODE);
				Element nextF=(Element)nNext.getParentNode();
				//				System.out.println(nextF.getAttribute("refID"));
				CalculXY.xBoite.put(nextF.getAttribute("refID"),l);
				ids.add(nextF.getAttribute("refID"));
				l+=20;
				//noOut=true;

			}else if(nOut.getLength()>1){
				for (int i=0; i<nOut.getLength();i++){
					Element et=(Element)nOut.item(i);
					String eID=et.getAttribute("refID");
					String exp="/MFHA_graph/link[init_interface[@refID='"+eID+"']]/finish_interface/@refID";
					String next=(String)TestXpath.evaluerSAX(CalculXY.source, exp,XPathConstants.STRING);
					String exp2="//node()[@type='MFHA_in_interface'][@refID='"+next+"']";
					Element nNext=(Element)TestXpath.evaluerSAX(CalculXY.source, exp2,XPathConstants.NODE);
					Element nextF=(Element)nNext.getParentNode();
					//					System.out.println(nextF.getAttribute("refID"));
					CalculXY.xBoite.put(nextF.getAttribute("refID"),l);
					ids.add(nextF.getAttribute("refID"));
				}
				l+=20;

			}else{
				Element ob=(Element)TestXpath.evaluerSAX(CalculXY.source, "//node()[@refID='"+lId+"']",XPathConstants.NODE);
				noOut=true;
			}
		}

		// add the without in interface to ids
		for (int y=0;y<boxWithoutIn.size();y++){
			if(ids.contains(boxWithoutIn.get(y))==false)
				ids.add(boxWithoutIn.get(y));
		}

		//place the obs add them to ids
		String obs="/MFHA_graph/node()[@type='MFHA_obs']";
		NodeList obList=(NodeList)TestXpath.evaluerSAX(source,obs,XPathConstants.NODESET);
		//		System.outs.println(obList.getLength());
		for(int y=0;y<obList.getLength();y++){
			Element ob=(Element)obList.item(y);
			if(ids.contains(ob.getAttribute("refID"))==false){
				CalculXY.xBoite.put(ob.getAttribute("refID"),l);
				l+=20;
				ids.add(ob.getAttribute("refID"));
			}
		}

		//let's treat the in interface
		Vector<String> newIds=new Vector<String>();
		int y=0;
		while (ids.size()<boxID.size()){
			//System.out.println("in while = "+ids.size());
			String r="//node()[@refID='"+ids.get(y)+"']/node()[@type='MFHA_in_interface']";
//			System.out.println("requte = "+r);
			//cette liste contient toutes les balises mfha_in_inteface lié au box
			NodeList ll=(NodeList) TestXpath.evaluerSAX(CalculXY.source,r, XPathConstants.NODESET);
			if((ll!=null) & (ll.getLength()>0) ){
				for (int g=0;g<ll.getLength();g++){
//					System.out.println("here");
					Element lt=(Element) ll.item(g);//<MFHA_in_interface>
					Element mm=(Element) TestXpath.evaluerSAX(CalculXY.source,"/MFHA_graph/link[finish_interface[@refID='"+lt.getAttribute("refID")+"']]/init_interface",XPathConstants.NODE);
//					System.out.println("ll requete = "+"/MFHA_graph/link[finish_interface[@refID='"+lt.getAttribute("refID")+"']]/init_interface");
//					System.out.println(mm);
					//c le id d'une mfha_ou_interface d'un box
					String mmID=mm.getAttribute("refID");
					Element rac=(Element)TestXpath.evaluerSAX(CalculXY.source,e+"/node()[@type='MFHA_out_interface'][@refID='"+mmID+"']",XPathConstants.NODE);
					Element p=(Element)rac.getParentNode();
					if(ids.contains(p.getAttribute("refID"))==false){
						Element pp=(Element) lt.getParentNode();
						int pos=CalculXY.xBoite.get(pp.getAttribute("refID"));
						CalculXY.xBoite.put(p.getAttribute("refID"),pos-10);
						ids.add(p.getAttribute("refID"));

					}
//					System.out.println(y);
					
				}
			}
			y++;

		}


		System.out.println("placed boxes : "+ids.toString());
		Collection<Integer> place=(Collection<Integer>)xBoite.values();
		System.out.println("places = "+place.toString());
		
		
//		System.out.println("places 2= "+xBoite.get("#2"));
//		System.out.println("places 3= "+xBoite.get("#3"));
//		System.out.println("places 4= "+xBoite.get("#4"));
//		System.out.println("places 5= "+xBoite.get("#5"));
//		System.out.println("places 6= "+xBoite.get("#6"));
//		System.out.println("places 7= "+xBoite.get("#7"));
//		System.out.println("places 8= "+xBoite.get("#8"));
//		System.out.println("places 9= "+xBoite.get("#9"));
//		System.out.println("places 10= "+xBoite.get("#10"));
//		System.out.println("places 33= "+xBoite.get("#33"));
//		System.out.println("places 100= "+xBoite.get("#100"));
		
		return CalculXY.xBoite;
	}
	
	

	public static HashMap<String,Integer> CalculY(HashMap<String, Integer> xp) throws FileNotFoundException{
		
		int h=200;
		Vector<String> y=new Vector<String>();
		String activId=(String)TestXpath.evaluerSAX(CalculXY.source,"/MFHA_graph/activator/@refID",XPathConstants.STRING);
		//set up the activator
		CalculXY.yBoite.put(activId,h);
		y.add(activId);
		h-=50;
		//put all the box without in under the activator
		Set<String> ids = xp.keySet();
		Vector<String> first=new Vector<String>();
		first.add(activId);
		Iterator<String> it = ids.iterator();
		while (it.hasNext()){
			String cle =it.next();
			int x=xp.get(cle);
			if((x==0) && (cle.equals(activId)==false)){
//				System.out.println("cle est = "+cle);
				CalculXY.yBoite.put(cle,h);
				y.add(cle);
				first.add(cle);
				h-=20;
			}
		}
		
		//pour ne prendre que les valeurs uniques
		Collection<Integer> place=(Collection<Integer>)xp.values();
		Set<Integer> up=new HashSet<Integer>(place);
		Iterator te=up.iterator();
		
//		while(te.hasNext()){
//			System.out.println("place ="+te.next());
//		}
		
//		it=ids.iterator();
//		while(it.hasNext()){
		while(te.hasNext()){
//			String id =it.next();
//			int x=xp.get(id);
			int x=(Integer)te.next();
			if(x!=0){
				int hh=250;
				Vector<String> same=CalculXY.getKeysFromValue(xp,x);
				for(int i=0;i<same.size();i++){
					CalculXY.yBoite.put(same.get(i),hh-30);
					y.add(same.get(i));
					hh-=30;
				}
				
			}
			
		}
		
		
		
		System.out.println("y placed : "+y.toString());
		Collection<Integer> yp=(Collection<Integer>)yBoite.values();
		System.out.println("places y = "+yp.toString());
		return CalculXY.yBoite;
	}
	
	  public static Vector<String> getKeysFromValue(HashMap<String,Integer>hm,Integer value){
		    Vector<String> list = new Vector<String>();
		    for(String o:hm.keySet()){
		        if(hm.get(o).equals(value)) {
		            list.add(o);
		        }
		    }
		    return list;
		  }

	public static void main(String args[]){
		try {
			CalculXY c=new CalculXY("/home/ubuntu/workspace_indigo/ProjetLongJSDAI/src/graphic/firstXML.xml");
			CalculXY.CalculX();
			CalculXY.CalculY(xBoite);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}